package com.oxygen.service.impl;

import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.util.StringUtils;

import com.oxygen.constants.Constant;
import com.oxygen.dto.ApiFinalResponse;
import com.oxygen.dto.ApiRequest;
import com.oxygen.dto.ApiResponse;
import com.oxygen.enums.ApiMethodEnum;
import com.oxygen.enums.MemcachedEnum;
import com.oxygen.util.DateTimeUtil;
import com.oxygen.util.HttpClientUtil;
import com.oxygen.util.HttpClientUtil.HttpMethod;
import com.oxygen.util.HttpRequestExceptionListener;
import com.oxygen.util.JsonUtil;
import com.oxygen.util.Md5Util;
import com.oxygen.util.MemcachedUtil;
import com.oxygen.util.RegexUtil;
import com.oxygen.web.DispatchAction;
import com.oxygen.web.SuperDispatcherServlet;

public abstract class SuperServiceImpl {
	private static final Logger log = Logger.getLogger(SuperServiceImpl.class);

	// @Value("${ccplay.commonservice.api.server}")
	// private String ccplayCommonserviceApiServer;
	@Autowired
	private TaskExecutor myExecutor;

	/**
	 * 构造请求响应对象
	 * 
	 * @param apiReq
	 * @param apiRsp
	 * @param msgArgs
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected final String buildResponse(ApiRequest apiReq, ApiResponse apiRsp, Object... msgArgs) {
		// 统一输出响应JSON
		if (apiReq.isJustNeedResult()) {
			return JsonUtil.objectToJson(apiRsp.getResults());
		} else {
			ApiFinalResponse finalRsp = new ApiFinalResponse();
			finalRsp.setVersion(apiReq.getApiVersion());
			finalRsp.setFunctionCode(apiReq.getFunctionCode());
			finalRsp.setIsSuccess(apiRsp.getReturnEnum().getIsSuccess());
			finalRsp.setCode(apiRsp.getReturnEnum().getCode());
			if (msgArgs != null && msgArgs.length > 0) {
				finalRsp.setMsg(MessageFormat.format(apiRsp.getReturnEnum().getMsg(), msgArgs));
			} else {
				finalRsp.setMsg(apiRsp.getReturnEnum().getMsg());
			}
			finalRsp.setCount(apiRsp.getCount());
			finalRsp.setResults(apiRsp.getResults());
			if (apiRsp.getCount() != null && !StringUtils.isEmpty(apiReq.get(Constant.PAGE_SIZE)) && RegexUtil.isPositiveInteger(apiReq.get(Constant.PAGE_SIZE).toString())) {
				int pageSize = apiReq.getInt(Constant.PAGE_SIZE);
				int page = 1;
				if (!StringUtils.isEmpty(apiReq.get(Constant.PAGE)) && RegexUtil.isPositiveInteger(apiReq.get(Constant.PAGE).toString())) {
					page = apiReq.getInt(Constant.PAGE);
				}
				int totalPages = apiRsp.getCount() / pageSize;
				if (apiRsp.getCount() % pageSize > 0) {
					totalPages++;
				}
				finalRsp.setTotalPages(totalPages);
				finalRsp.setCurPage(page);
				finalRsp.setPageSize(pageSize);
			}
			return JsonUtil.objectToJson(finalRsp);
		}
	}
	
	/**
	 * 构造请求响应对象
	 * 
	 * @param apiReq
	 * @param apiRsp
	 * @param dateFomatter
	 * @param msgArgs
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected final String buildResponse(ApiRequest apiReq, ApiResponse apiRsp, String dateFomatter, Object... msgArgs) {
		// 统一输出响应JSON
		if (apiReq.isJustNeedResult()) {
			return JsonUtil.objectToJson(apiRsp.getResults(), null, dateFomatter);
		} else {
			ApiFinalResponse finalRsp = new ApiFinalResponse();
			finalRsp.setVersion(apiReq.getApiVersion());
			finalRsp.setFunctionCode(apiReq.getFunctionCode());
			finalRsp.setIsSuccess(apiRsp.getReturnEnum().getIsSuccess());
			finalRsp.setCode(apiRsp.getReturnEnum().getCode());
			if (msgArgs != null && msgArgs.length > 0) {
				finalRsp.setMsg(MessageFormat.format(apiRsp.getReturnEnum().getMsg(), msgArgs));
			} else {
				finalRsp.setMsg(apiRsp.getReturnEnum().getMsg());
			}
			finalRsp.setCount(apiRsp.getCount());
			finalRsp.setResults(apiRsp.getResults());
			if (apiRsp.getCount() != null && !StringUtils.isEmpty(apiReq.get(Constant.PAGE_SIZE)) && RegexUtil.isPositiveInteger(apiReq.get(Constant.PAGE_SIZE).toString())) {
				int pageSize = apiReq.getInt(Constant.PAGE_SIZE);
				int page = 1;
				if (!StringUtils.isEmpty(apiReq.get(Constant.PAGE)) && RegexUtil.isPositiveInteger(apiReq.get(Constant.PAGE).toString())) {
					page = apiReq.getInt(Constant.PAGE);
				}
				int totalPages = apiRsp.getCount() / pageSize;
				if (apiRsp.getCount() % pageSize > 0) {
					totalPages++;
				}
				finalRsp.setTotalPages(totalPages);
				finalRsp.setCurPage(page);
				finalRsp.setPageSize(pageSize);
			}
			
			return JsonUtil.objectToJson(finalRsp, null, dateFomatter);
			
		}
	}

	/**
	 * 是否为业务参数
	 * 
	 * @param paramName
	 * @return
	 */
	protected boolean isBusinessParam(String paramName) {
		if (Constant.API_KEY.equals(paramName) || Constant.ACCESS_TOKEN.equals(paramName) || Constant.FUNCTION_CODE.equals(paramName) || Constant.REQUEST_IP.equals(paramName)
				|| Constant.JUST_NEED_RESULT.equals(paramName) || Constant.OLD_VERSION.equals(paramName) || Constant.SITE_ID.equals(paramName) || Constant.PAGE.equals(paramName)
				|| Constant.PAGE_SIZE.equals(paramName) || Constant.PAGING_URL.equals(paramName) || Constant.AUTH_TOKEN.equals(paramName) || Constant.USER_AGENT.equals(paramName)) {
			return false;
		}
		return true;
	}

	/**
	 * 检测给定参数列表里是否有空值的参数
	 * 
	 * @param apiReq
	 * @param parameters
	 * @return
	 */
	protected boolean checkNotEmptyParameter(ApiRequest apiReq, String[] parameters) {
		if (parameters != null) {
			for (String name : parameters) {
				if (StringUtils.isEmpty(apiReq.get(name))) {
					return true;
				}
			}
		}
		return false;
	}

	protected void setDefaultPageSize(ApiRequest apiReq) {
		if (StringUtils.isEmpty(apiReq.get(Constant.PAGE_SIZE))) {
			apiReq.put(Constant.PAGE_SIZE, Constant.DEFAULT_PAGE_SIZE);
		}
	}

	protected void setDefaultPageSize(ApiRequest apiReq, int pageSize) {
		if (!StringUtils.isEmpty(apiReq)) {
			apiReq.put(Constant.PAGE_SIZE, pageSize);
		}
	}

	protected String getStaticUrl(int staticServerCount, String serverPrefix, String resourcePath, String picSize) {
		if (resourcePath == null || "".equals(resourcePath)) {
			return null;
		}
		if (picSize != null && !"".equals(picSize)) {
			resourcePath = resourcePath + picSize;
		}
		int serverId = getStaticServerId(staticServerCount, resourcePath);
		serverPrefix = MessageFormat.format(serverPrefix, serverId);
		return serverPrefix + resourcePath;
	}

	protected String getStaticUrl(int staticServerCount, String serverPrefix, String resourcePath) {
		return this.getStaticUrl(staticServerCount, serverPrefix, resourcePath, null);
	}

	private int getStaticServerId(int serverCount, String resourcePath) {
		int serverId = 0;
		String md5 = Md5Util.encodeString(resourcePath);
		char firstChar = md5.charAt(0);
		serverId = Integer.valueOf(firstChar) % serverCount;
		return serverId + 1;
	}

	protected String callApi(final String apiServer, final String apiKey, final String functionCode, Map<String, Object> inMap, Map<String, String> header) {
		inMap.put(Constant.API_KEY, apiKey);
		inMap.put(Constant.ACCESS_TOKEN, Constant.DEFAULT_ACCESS_TOKEN);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put(functionCode, inMap);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		final String dataJson = JsonUtil.objectToJson(dataMap, Map.class);
		paramMap.put(Constant.DATA, dataJson);
		HttpClientUtil clientUtil = new HttpClientUtil();
		ApiRequest req = DispatchAction.getCurrentReqeust();
		String ip = (String) inMap.get("ip");
		if (StringUtils.isEmpty(ip)) {
			// ip 没有的情况下, 一秒内落到同一台服务上
			ip = req == null ? DateTimeUtil.formatDateTime(new Date()) : req.getRequestIp();
		}
		header.put("X-Hash-ip", ip);
		clientUtil.setHttpSetting(header);
		// 服务器应用异常预警通知
		clientUtil.setExceptionListener(new HttpRequestExceptionListener() {
			@Override
			public void exceptionData(final Map<String, String> data) {
				String httpCode = data.get("code");
				final String exception = data.get("exception");
				if (!"200".equals(httpCode)) {
					myExecutor.execute(new Runnable() {
						@Override
						public void run() {
							String alterContent = "inner invoke error: service[" + ApiMethodEnum.getApiServerEnum(functionCode) + "] --- functionCode[" + functionCode + "] --- msg[" + exception + "]";
							// TODO:预警监控
							log.info("error:" + alterContent);
						}
					});
				}
			}
		});
		String retJson = clientUtil.doHttpPost(apiServer, paramMap);
		return retJson;
	}

	/**
	 * 发送HTTP请求
	 * 
	 * @param url
	 * @param method
	 * @param paramMap
	 * @return
	 */
	protected String sendHttpReqeust(String url, String method, Map<String, Object> paramMap) {
		String retJson = null;
		HttpClientUtil clientUtil = new HttpClientUtil();
		if (HttpMethod.get.name().equals(method)) {
			retJson = clientUtil.doHttpGet(url, paramMap);
		} else if (HttpMethod.post.name().equals(method)) {
			retJson = clientUtil.doHttpPost(url, paramMap);
		}
		return retJson;
	}

	/**
	 * 取memcached缓存
	 * 
	 * @param key
	 * @return
	 */
	protected Object getOpenCache(String key) {
		Object isOpen = MemcachedUtil.getInstance().get(MemcachedEnum.memcache_open_key.getCode());
		if (isOpen != null && "true".equals(isOpen.toString().trim())) {
			return MemcachedUtil.getInstance().get(key);
		} else {
			long threadId = Thread.currentThread().getId();
			log.info("{logId:" + SuperDispatcherServlet.getLogIdByThreadId(threadId) + ",msg: memcached data for application is not open ");
		}
		return null;
	}
	/**
	 * 存放memcached缓存
	 * @param key
	 * @param value
	 * @return
	 */
	protected boolean setCache(String key, int expSecond, String value) {
	    return MemcachedUtil.getInstance().set(key,expSecond, value);
	}
	
	/**
	 * 取memcached缓存
	 * @param key
	 * @return
	 */
	protected Object getCache(String key) {
	    return MemcachedUtil.getInstance().get(key);
	}

}
